<template>
  <div class="container">
    <view class="left-box">
      <div class="header-box">
        <div class="title-box">
          <span>可选</span>
          <span>
            {{ rightOptionData.filterSelectedOption.length }}/{{ leftOptionData.total }}
          </span>
        </div>
        <div class="serach-box">
          <Input
            v-model:value="leftOptionData.keyWord"
            placeholder="请输入关键字搜索"
            @input="leftOptionData.handleSearch"
            clearable
          />
        </div>
      </div>
      <div class="option-box">
        <Checkbox
          v-for="item in leftOptionData.filterOptions"
          :key="item.value"
          :checked="leftOptionData.isChecked(item.value)"
          @click="() => leftOptionData.handleCheckChange(item)"
        >
          {{ item.label }}
        </Checkbox>
      </div>
      <div class="footer-box">
        <Checkbox
          v-model:checked="leftOptionData.checkAll"
          :indeterminate="leftOptionData.indeterminate"
          @change="leftOptionData.handleCheckAllChange"
        >
          前页全选
        </Checkbox>
        <Pagination
          v-if="paginationData.total && openPagination"
          v-model:current="leftOptionData.current"
          :page-size="leftOptionData.pageSize"
          simple
          :total="leftOptionData.total"
          @change="leftOptionData.handlePaginationChange"
        ></Pagination>
      </div>
    </view>
    <div class="center-box">
      {{ rightOptionData.filterSelectedOption.length }}/{{ leftOptionData.total }}
    </div>
    <view class="right-box">
      <div class="header-box">
        <div class="title-box">
          <span>已选 {{ rightOptionData.originalSelectedValue.length }} 项目</span>
          <DeleteOutlined @click="rightOptionData.handleDelAll()" />
        </div>
        <div class="serach-box">
          <Input v-model:value="rightOptionData.stateKeyWord" placeholder="请输入关键字搜索" />
        </div>
      </div>
      <div class="selected-box">
        <div
          class="item-box"
          v-for="item in rightOptionData.filterSelectedOption"
          :key="item.value"
        >
          <span>{{ item.label }}</span>
          <CloseOutlined @click="rightOptionData.handleDel(item.value)"/>
        </div>
      </div>
    </view>
  </div>
</template>
<script setup lang="ts">
  import { DeleteOutlined,CloseOutlined } from '@ant-design/icons-vue';
  import { Input, Checkbox, Pagination } from 'ant-design-vue';
  import { ILeftOptionData, IRightOptionData, OptionsType } from './types';
  import { computed, nextTick, reactive, watch } from 'vue';
  import { CheckboxChangeEvent } from 'ant-design-vue/es/checkbox/interface';
  const props = defineProps({
    option: {
      type: Array as PropType<OptionsType[]>,
      default: () => [],
    },
    paginationData: {
      type: Object as PropType<{ current: number; total: number; pageSize: number }>,
      default: () => ({ current: 0, total: 0, pageSize: 0 }),
    },
    searchLoca: {
      type: Boolean,
      default: () => false,
    },
    openPagination: {
      type: Boolean,
      default: () => true,
    },
  });

  const emtis = defineEmits(['selectedValue', 'pagination', 'search']);

  // 左边
  const leftOptionData: ILeftOptionData = reactive<ILeftOptionData>({
    
    keyWord: '',

    current: props.paginationData.current,
    total: props.paginationData.total,
    pageSize: props.paginationData.pageSize,

    checkAll: false,
    indeterminate: false,

    originalOptions: computed(() => props.option) as unknown as OptionsType[],

    originalOptionsValue: computed(() =>
      leftOptionData.originalOptions.map((item) => item.value),
    ) as unknown as string[],

    filterOptions: computed(() => {
      if (!props.searchLoca) return leftOptionData.originalOptions;
      return leftOptionData.originalOptions.filter(
        (item) => !leftOptionData.keyWord || item.label.includes(leftOptionData.keyWord),
      );
    }) as unknown as OptionsType[],

    handleSearch: (e: ChangeEvent) => {
      if (props.searchLoca) return;
      emtis('search', e.target.value);
    },

    isChecked: (value: string) => {
      return rightOptionData.originalSelectedOption.some((item) => item.value === value);
    },

    handleCheckChange: (option: OptionsType) => {
      const index = rightOptionData.originalSelectedOption.findIndex(
        (item) => item.value === option.value,
      );
      if (index === -1) {
        rightOptionData.originalSelectedOption.push(option);
      } else {
        rightOptionData.originalSelectedOption.splice(index, 1);
      }
    },

    handleCheckAllChange: (e: CheckboxChangeEvent) => {
      if (e.target.checked) {
        const res = leftOptionData.originalOptions.filter(
          (item) => !rightOptionData.originalSelectedValue.includes(item.value),
        );
        rightOptionData.originalSelectedOption.push(...res);
      } else {
        rightOptionData.originalSelectedOption = rightOptionData.originalSelectedOption.filter(
          (item) => !leftOptionData.originalOptionsValue.includes(item.value),
        );
      }
    },

    updateCheckAll: () => {
      emtis('selectedValue', rightOptionData.originalSelectedValue);

      const checkAllStatus = leftOptionData.originalOptionsValue.every((item) =>
        rightOptionData.originalSelectedValue.includes(item),
      );

      if (checkAllStatus) {
        leftOptionData.indeterminate = false;
        leftOptionData.checkAll = true;
        return;
      }

      const indeterminateStatus = leftOptionData.originalOptionsValue.some((item) =>
        rightOptionData.originalSelectedValue.includes(item),
      );

      leftOptionData.indeterminate = indeterminateStatus;
      leftOptionData.checkAll = false;
    },

    handlePaginationChange: (page: number, pageSize: number) => {
      emtis('pagination', { current: page, pageSize: pageSize });
      nextTick(() => {
        leftOptionData.updateCheckAll();
      });
    },
  });

  watch(
    () => props.paginationData.total,
    () => {
      leftOptionData.current = props.paginationData.current;
      leftOptionData.total = props.paginationData.total;
      leftOptionData.pageSize = props.paginationData.pageSize;
    },
  );

  // 右边
  const rightOptionData: IRightOptionData = reactive<IRightOptionData>({
    stateKeyWord: '',
    originalSelectedOption: [],

    originalSelectedValue: computed(() =>
      rightOptionData.originalSelectedOption.map((item) => item.value),
    ) as unknown as string[],

    filterSelectedOption: computed(() => {
      return rightOptionData.originalSelectedOption.filter((item) =>
        item?.label.includes(rightOptionData.stateKeyWord),
      );
    }) as unknown as OptionsType[],

    handleDel: (value: string) => {
      rightOptionData.originalSelectedOption = rightOptionData.originalSelectedOption.filter(
        (item) => item.value !== value,
      );
    },
    handleDelAll: () => {
      rightOptionData.originalSelectedOption = [];
    },
  });

  // 监听选择

  watch(
    () => rightOptionData.originalSelectedValue,
    () => {
      leftOptionData.updateCheckAll();
    },
  );
</script>
<style lang="less" scoped>
  .container {
    display: flex;
    align-items: center;
    gap: 10px;
    .header-box {
      padding: 10px;
      background-color: #f7f8fa;
      .title-box {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 10px;
      }
    }

    .left-box {
      border: 1px solid #e5e6eb;
      height: 480px;
      flex: 1;
      position: relative;
      .option-box {
        padding: 20px;
        padding-bottom: 0;
        overflow-y: auto;
        height: 340px;
        display: flex;
        flex-direction: column;
        gap: 10px;
        .ant-checkbox-wrapper + .ant-checkbox-wrapper{
          margin: 0;
        }
      }
      .footer-box {
        width: 100%;
        position: absolute;
        left: 0;
        bottom: 0;
        padding: 10px;
        border-top: 1px solid #e5e6eb;
        display: flex;
        justify-content: space-between;
        align-items: center;
      }
    }
    .center-box {
      width: 50px;
      text-align: center;
    }
    .right-box {
      border: 1px solid #e5e6eb;
      height: 480px;
      flex: 1;
      .selected-box {
        height: 390px;
        display: flex;
        flex-direction: column;
        gap: 10px;
        padding: 20px;
        overflow-y: auto;
        .item-box {
          display: flex;
          align-items: center;
          justify-content: space-between;
        }
      }
    }
  }
</style>
